﻿namespace PocketE6B.Engine
{
    using System;

    /// <summary>
    /// Performs the functions of an E6B flight computer.
    /// </summary>
    public class E6B
    {
        /// <summary>Gets or sets the desired course, in degrees.</summary>
        public double Course { get; set; }

        /// <summary>Gets or sets the wind direction, in degrees.</summary>
        public double WindDirection { get; set; }

        /// <summary>Gets or sets the true airspeed, in knots per hour.</summary>
        public double TrueAirspeed { get; set; }

        /// <summary>Gets or sets the wind speed, in knots per hour.</summary>
        public double WindSpeed { get; set; }

        /// <summary>Gets or sets the aircraft's ground speed, in knots per hour.</summary>
        public double Groundspeed { get; set; }

        /// <summary>
        /// Calculates the Wind Correction Angle (WCA).  This calculation indicates
        /// the heading the aircraft must fly in order to maintain a desired track 
        /// along the ground, compensating for wind direction and velocity.
        /// All values are rounded to the nearest degree.
        /// </summary>
        /// <returns>
        ///     The Wind Correction Angle, in degrees.  Negative values indicate
        ///     a left-hand turn and positive values indicate a right-hand turn.
        /// </returns>
        public double WindCorrectionAngle()
        {
            double windDir = Trig.DegreesToRadians(this.WindDirection);
            double course = Trig.DegreesToRadians(this.Course);
            return Trig.RadiansToDegrees(Math.Asin((this.WindSpeed * Math.Sin(windDir - course)) / this.TrueAirspeed));
        }

        /// <summary>
        /// Calculates the true ground speed of the aircraft.  All values are
        /// rounded to the nearest knot per hour.
        /// </summary>
        /// <returns>The aircraft's ground speed.</returns>
        public double TrueGroundspeed()
        {
            double windDir = Trig.DegreesToRadians(this.WindDirection);
            double course = Trig.DegreesToRadians(this.Course);
            double wca = Trig.DegreesToRadians(this.WindCorrectionAngle());

            double squaredSpeeds = Math.Pow(this.TrueAirspeed, 2) + Math.Pow(this.WindSpeed, 2);
            double geomPart = 2 * this.TrueAirspeed * this.WindSpeed * Math.Cos((course + wca) - windDir);
            return Math.Round(Math.Sqrt(squaredSpeeds - geomPart));
        }
    }
}
